package com.cq.hd.order.render.impl;

import com.cq.hd.common.enums.biz.ActiveTypeEnum;
import com.cq.hd.common.enums.biz.CalCommissionTypeEnum;
import com.cq.hd.common.enums.biz.OrderItemTypeEnum;
import com.cq.hd.common.enums.biz.SubsidyStateEnum;
import com.cq.hd.order.api.dto.CreateOrderDto;
import com.cq.hd.order.api.dto.OrderCommissionDto;
import com.cq.hd.order.render.OrderContext;
import com.cq.hd.order.render.OrderRenderStepEnum;
import com.cq.hd.order.render.dto.ActiveGoodsDto;
import com.cq.hd.order.render.dto.GoodsPriceDetailDto;
import com.cq.hd.order.render.dto.PriceDetailDto;
import com.cq.hd.product.api.vo.ActiveVo;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * 计算商户、商家分账
 *
 * @author much
 * @since 2024/09/15 13:31
 */
@Component
public class SplitAccRender extends AbstractRenderStep {

    @Override
    public OrderRenderStepEnum step() {
        return OrderRenderStepEnum.SPLIT_ACC;
    }

    @Override
    public void render(OrderContext orderContext) {
        // 商家订单收入(当实付金额大于商品总额，订单收入=实付金额-商品总额-全核销佣金)
        calculateOrderIncomeAmt(orderContext);
        // 红包
        splitRedPackageAmt(orderContext);
        // 分销金额
        splitDistributionOrderAmt(orderContext);
        // 计算每个商品的本金和补贴
        splitMerchantAmtAndSubsidyAmt(orderContext);
    }

    // 计算商家的订单收入（订单收入= 实付金额-商品总额-全核销佣金）
    private BigDecimal calculateOrderIncomeAmt(OrderContext orderContext) {
        PriceDetailDto priceDetailDto = orderContext.getPriceDetailDTO();
        OrderCommissionDto commissionDto = orderContext.getCommissionDto();
        BigDecimal payPrice = priceDetailDto.getPayPrice();
        // 订单收入(当实付金额大于商品总额，订单收入=实付金额-商品总额-全核销佣金)
        BigDecimal orderIncomeAmt = payPrice.subtract(priceDetailDto.getTotalGoodsPrice())
                .subtract(commissionDto.getActualCommissionAmt());

        ActiveVo activeVo = orderContext.getActiveVo();
        // 纯报名无需补贴
        if (ActiveTypeEnum.ENROLL.getValue().equals(activeVo.getActiveType())) {
            orderContext.setNeedSubsidy(false);
        } else {
            // 是否需要补贴(计算得出的订单收入小于0)
            orderContext.setNeedSubsidy(orderIncomeAmt.compareTo(BigDecimal.ZERO) < 0);
        }

        // 如果收入为负数，说明出现需要补贴
        if (orderIncomeAmt.compareTo(BigDecimal.ZERO) < 0) {
            orderIncomeAmt = BigDecimal.ZERO;
        }
        priceDetailDto.setOrderIncomeAmt(orderIncomeAmt);
        return orderIncomeAmt;
    }

    private void splitRedPackageAmt(OrderContext orderContext) {
        List<ActiveGoodsDto> activeGoodsList = orderContext.getActiveGoods();
        PriceDetailDto priceDetailDto = orderContext.getPriceDetailDTO();
        if (priceDetailDto.getTotalGoodsPrice().compareTo(BigDecimal.ZERO) > 0) {
            for (ActiveGoodsDto goods : activeGoodsList) {
                GoodsPriceDetailDto goodsPriceDetailDto = goods.getGoodsPriceDetailDto();
                BigDecimal itemRedPackageAmt = goods.getGoodsPrice().multiply(priceDetailDto.getRedPacketAmt())
                        .divide(priceDetailDto.getTotalGoodsPrice(), 2, RoundingMode.HALF_UP);
                goodsPriceDetailDto.setRedPacketAmt(itemRedPackageAmt);
            }
        }
    }

    private void splitDistributionOrderAmt(OrderContext orderContext) {
        List<ActiveGoodsDto> activeGoodsList = orderContext.getActiveGoods();
        PriceDetailDto priceDetailDto = orderContext.getPriceDetailDTO();
        BigDecimal payPrice = priceDetailDto.getPayPrice();
        BigDecimal totalGoodsPrice = priceDetailDto.getTotalGoodsPrice();
        for (ActiveGoodsDto goods : activeGoodsList) {
            GoodsPriceDetailDto goodsPriceDetailDto = goods.getGoodsPriceDetailDto();
            if (orderContext.getNeedSubsidy()) {
                if (OrderItemTypeEnum.SIGN_IN.getValue().equals(goods.getType())) {
                    goodsPriceDetailDto.setDistributionOrderAmt(goods.getGoodsPrice());
                } else {
                    // 计算分销金额=商品价格/商品总价 * 实付金额
                    BigDecimal totalSignInFee = priceDetailDto.getTotalSignInFee();
                    BigDecimal distributionOrderAmt = goods.getGoodsPrice().multiply(payPrice.subtract(totalSignInFee))
                            .divide(totalGoodsPrice.subtract(totalSignInFee), 2, RoundingMode.HALF_UP);
                    goodsPriceDetailDto.setDistributionOrderAmt(distributionOrderAmt);
                }
            } else {
                goodsPriceDetailDto.setDistributionOrderAmt(goods.getGoodsPrice());
            }
        }
    }

    // 分配本金和补贴
    private void splitMerchantAmtAndSubsidyAmt(OrderContext orderContext) {
        if (orderContext.getNeedSubsidy()) {
            // 需要补贴
            doSplitMerchantAmtAndSubsidyAmt(orderContext);
        } else {
            // 无需补贴
            doSplitMerchantAmtWithoutSubsidy(orderContext);
        }
    }

    // 不需要补贴
    private void doSplitMerchantAmtWithoutSubsidy(OrderContext orderContext) {
        List<ActiveGoodsDto> activeGoodsList = orderContext.getActiveGoods();

        ActiveVo activeVo = orderContext.getActiveVo();
        PriceDetailDto priceDetailDTO = orderContext.getPriceDetailDTO();
        OrderCommissionDto commissionDto = orderContext.getCommissionDto();
        BigDecimal actualCommissionAmt = commissionDto.getActualCommissionAmt();
        // 如果是纯报名，则本金要减去佣金
        BigDecimal merchantAmt = null;
        if (ActiveTypeEnum.ENROLL.getValue().equals(activeVo.getActiveType())) {
//            BigDecimal activePrice = activeVo.getActivePrice();
            BigDecimal activePrice = priceDetailDTO.getActivePrice();
            BigDecimal payPrice = priceDetailDTO.getPayPrice();
            BigDecimal orderPrice = priceDetailDTO.getOrderPrice();
            BigDecimal subtract = priceDetailDTO.getPayPrice().subtract(actualCommissionAmt);
            if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                if (priceDetailDTO.getOrderPrice().compareTo(BigDecimal.ZERO) > 0) {
                    // 计算商户订单本金=商品价格/商品总价 * (实付金额-佣金)
                    merchantAmt = activePrice.multiply(payPrice.subtract(actualCommissionAmt)).divide(orderPrice, 2, BigDecimal.ROUND_HALF_UP);
                } else {
                    merchantAmt = BigDecimal.ZERO;
                }
            }
        }

        for (ActiveGoodsDto goods : activeGoodsList) {
            GoodsPriceDetailDto goodsPriceDetailDto = goods.getGoodsPriceDetailDto();
            if (merchantAmt != null) {
                goodsPriceDetailDto.setMerchantAmt(merchantAmt);
            } else {
                goodsPriceDetailDto.setMerchantAmt(goods.getGoodsPrice());
            }
            goodsPriceDetailDto.setMerchantSubsidyAmt(BigDecimal.ZERO);
            goodsPriceDetailDto.setTotalSubsidyAmt(BigDecimal.ZERO);
        }
    }

    // 计算本金和补贴
    private void doSplitMerchantAmtAndSubsidyAmt(OrderContext orderContext) {
        ActiveVo activeVo = orderContext.getActiveVo();
        List<ActiveGoodsDto> activeGoodsList = orderContext.getActiveGoods();
        for (ActiveGoodsDto goods : activeGoodsList) {
            GoodsPriceDetailDto goodsPriceDetailDto = goods.getGoodsPriceDetailDto();
            // 商品金额
            BigDecimal goodsPrice = goods.getGoodsPrice();

            if (firstCalculateMerchantAmt(orderContext)) {
                // 先计算本金
                BigDecimal merchantAmt = calculateMerchantAmtBeforeSubsidy(goods, orderContext);
                goodsPriceDetailDto.setMerchantAmt(merchantAmt);

                // 补贴
                // 计算总补贴=商品价格-本金
                BigDecimal totalSubsidyAmt = goodsPrice.subtract(merchantAmt);
                goodsPriceDetailDto.setTotalSubsidyAmt(totalSubsidyAmt);
                // 计算商户订单补贴(该订单商场补贴的金额)=总补贴-红包
                BigDecimal merchantSubsidyAmt = totalSubsidyAmt.subtract(goodsPriceDetailDto.getRedPacketAmt());
                goodsPriceDetailDto.setMerchantSubsidyAmt(merchantSubsidyAmt);
            } else if (SubsidyStateEnum.MANUAL.getValue().equals(activeVo.getSubsidyState())){
                // 手动设置补贴金额
                BigDecimal subsidyAmt = goods.getSubsidyAmt() == null ? BigDecimal.ZERO : goods.getSubsidyAmt();
                goodsPriceDetailDto.setTotalSubsidyAmt(subsidyAmt);
                goodsPriceDetailDto.setMerchantSubsidyAmt(subsidyAmt);
                // 计算商户订单本金(按比例分配的用户支付的订单款)=商品价格-手动设置补贴金额
                BigDecimal merchantAmt = goodsPrice.subtract(subsidyAmt);
                goodsPriceDetailDto.setMerchantAmt(merchantAmt);
            }
        }
    }

    // 优先计算本金
    private BigDecimal calculateMerchantAmtBeforeSubsidy(ActiveGoodsDto activeGoodsDto, OrderContext orderContext) {
        PriceDetailDto priceDetailDto = orderContext.getPriceDetailDTO();
        OrderCommissionDto commissionDto = orderContext.getCommissionDto();
        BigDecimal payPrice = priceDetailDto.getPayPrice();
        BigDecimal actualCommissionAmt = commissionDto.getActualCommissionAmt();
        BigDecimal totalGoodsPrice = priceDetailDto.getTotalGoodsPrice();
        BigDecimal totalSignInFee = priceDetailDto.getTotalSignInFee();
        // 如果是签到费，则直接是签到费
        if (OrderItemTypeEnum.SIGN_IN.getValue().equals(activeGoodsDto.getType())) {
            return activeGoodsDto.getGoodsPrice();
        } else {
            BigDecimal baseAmt = payPrice.subtract(actualCommissionAmt).subtract(totalSignInFee);
            return activeGoodsDto.getGoodsPrice().multiply(baseAmt)
                    .divide(totalGoodsPrice.subtract(totalSignInFee), 2, RoundingMode.HALF_UP);
        }
    }

    // 是否先执行本金的计算
    private Boolean firstCalculateMerchantAmt(OrderContext orderContext) {
        ActiveVo activeVo = orderContext.getActiveVo();
        // 补贴类型(0-未设置,1-自动按比例分摊,2-手动设置)
        Integer subsidyState = activeVo.getSubsidyState();
        // 0-未设置,1-自动按比例分摊
        if (SubsidyStateEnum.NO.getValue().equals(subsidyState) || SubsidyStateEnum.AUTO.getValue().equals(subsidyState)) {
            return true;
        }
        // 如果是专属佣金，则按照自动比例去计算，否则，则按照手动设置去计算
        OrderCommissionDto commissionDto = orderContext.getCommissionDto();
        if (CalCommissionTypeEnum.EXCLUSIVE_COMMISSION.getValue().equals(commissionDto.getCalCommissionType())) {
            return true;
        }
        return false;
    }

}
